<template>
  <form class="x-form" @submit.prevent="handleSubmit">
    <div class="x-form__item"
      v-for="item in formItems"
      :key="item.prop"
      :class="['x-form__item', { focus: item.focus, unfocus: !item.focus }]"
      @click="handleFocus(item.prop, $event)"
    >
      <label class="x-form__label">{{ item.label }}</label>

      <template v-if="item.type === 'input'">
        <input
          :class="['x-input', 'x-form__value']"
          v-model="formData[item.prop]"
          :placeholder="item.placeholder"
          :type="item.password ? 'password' : 'text'"
          @input="handleInput(item.prop, $event)"
          @blur="handleBlur(item.prop, $event)"
        />
      </template>

      <template v-if="item.type === 'select'">
        <select class="x-select x-form__value" v-model="formData[item.prop]">
          <option v-for="option in item.options" :key="option.value" :value="option.value">{{ option.label }}</option>
        </select>
      </template>

      <template v-if="item.type === 'checkbox'">
        <input class="x-checkbox x-form__value" type="checkbox" v-model="formData[item.prop]" />
      </template>

      <template v-if="item.type === 'radio'">
        <input class="x-radio x-form__value" type="radio" v-model="formData[item.prop]" />
      </template>
    </div>

    <slot name="footer">
      <div class="x-form__footer">
        <button class="x-button x-button--danger" @click="handleCancel">取消</button>
        <button class="x-button x-button--primary" type="submit">提交</button>
      </div>
    </slot>
  </form>
</template>

<script lang="ts">
import { defineComponent, ref, onMounted } from 'vue';
import type { PropType } from 'vue';
import type { FormItem } from './IFormItem'

export default defineComponent({
  name: 'XForm',
  props: {
    modelValue: { type: Object, required: true },
    rules: { type: Object, default: () => ({}) },
    labelWidth: { type: String, default: '100px' },
    items: { type: Array as PropType<FormItem[]>, default: () => [] },
    defaultFocus: { type: Boolean, default: true },
  },
  watch: {
    modelValue: {
      handler(val) {
        this.formData = val
      },
      immediate: true,
    }
  },
  setup(props, { emit }) {
    const formData = ref({})
    const formItems = ref<FormItem[]>([])

    const initFormItems = () => {
      formItems.value = props.items.map((item: FormItem) => ({
        ...item,
        focus: props.defaultFocus
      }))
    }

    onMounted(() => {
      initFormItems()
    })

    /**
     * 聚焦事件
     * @param prop 属性名
     * @param event 事件对象
     */
    const handleFocus = (prop: string, event: Event) => {

      // 设置聚焦状态
      const item = formItems.value.find(item => item.prop === prop)
      if (item) {
        item.focus = true
      }

      // 其它item设置失焦
      formItems.value.forEach(item => {
        if (item.prop !== prop) {
          item.focus = false
        }
      })

      // 触发聚焦事件
      emit('focus', { ...formData.value, [prop]: (event.target as HTMLInputElement).value })
    }

    /**
     * 失去焦点事件
     * @param prop 属性名
     * @param event 事件对象
     */
    const handleBlur = (prop: string, event: Event) => {

      // 设置失焦状态 失焦设置所有item为true
      formItems.value.forEach(item => {
        item.focus = props.defaultFocus
      })

      emit('blur', { ...formData.value, [prop]: (event.target as HTMLInputElement).value })
    }

    const handleInput = (prop: string, event: Event) => {
      // emit('update:modelValue', { ...formData.value, [prop]: (event.target as HTMLInputElement).value })
      emit('input', { ...formData.value, [prop]: (event.target as HTMLInputElement).value })
    }

    const handleCancel = () => {
      emit('cancel', formData.value)
    }
    
    const handleSubmit = () => {
      emit('submit', formData.value)
    }

    return {
      formData,
      formItems,
      handleInput,
      handleCancel,
      handleSubmit,
      handleFocus,
      handleBlur
    }
  }
})
</script>

<style lang="scss" scoped>
</style>